uniform extern float4x4 gVP;
uniform extern texture  gTex;
uniform extern float3   gEyePosW;
uniform extern float    gPSystemTime;
uniform extern float    gAccel;

sampler Tex = sampler_state
{
	Texture = <gTex>;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = LINEAR;
	AddressU  = CLAMP;
    AddressV  = CLAMP;
};

struct VSInput
{
    float3 posW     : POSITION0;
	float2 texc     : TEXCOORD0;
	float2 offset   : TEXCOORD1;
	float3 velocity : TEXCOORD2; // velocity or axis
	float iniTime   : TEXCOORD3;
	float maxTime   : TEXCOORD4;
	float3 axis     : TEXCOORD5;
	float3 color    : COLOR0;
};


struct VSOutput
{
    float4 posH  : POSITION0;
	float2 texc  : TEXCOORD0;
	float4 color : COLOR0;
};



float3 RotateBillboardVertex(float3 posW, float2 offset, float3 viewDirW)
{
	float3 rightVec = normalize(cross(viewDirW, float3(0,1,0)));
    float3 upVec = normalize(cross(rightVec, viewDirW));
	
	
	posW += rightVec * offset.x;
    posW += upVec * offset.y;

    return posW;
}


////////
VSOutput DynamicBillboardParticleVS(VSInput input)
{
	VSOutput output = (VSOutput)0;
	
	float t = gPSystemTime - input.iniTime;

	float3 posW = input.posW + input.velocity * t * (1 + 0.5f * gAccel * t);
    posW = RotateBillboardVertex(posW, input.offset, gEyePosW - posW);
    
    output.posH = mul(float4(posW, 1.0f), gVP);
	output.texc = input.texc;
	
	
	
	output.color = 1.0f - t/input.maxTime;

    return output;
}

VSOutput AxisAlignedBillboardParticleVS(VSInput input)
{
	VSOutput output = (VSOutput)0;
	
	float t = gPSystemTime - input.iniTime;
  
    
    float3 viewDir = gEyePosW - input.posW;
    float3 axis = normalize(input.axis);
    
    float3 rightVec = normalize(cross(viewDir, axis));
	
	float3 posW = input.posW;
	posW += rightVec * input.offset.x;
    posW += axis * input.offset.y;
    

    output.posH = mul(float4(posW, 1.0f), gVP);
	output.texc = input.texc;

	output.color = (1.0f - t/input.maxTime) * float4(input.color, 1.0f);

    return output;
}


VSOutput DynamicAxisAlignedBillboardParticleVS(VSInput input)
{
	VSOutput output = (VSOutput)0;
	
	float t = gPSystemTime - input.iniTime;
  
    
    float3 viewDir = gEyePosW - input.posW;
    float3 axis = normalize(input.axis);
    
    float3 rightVec = normalize(cross(viewDir, axis));
	
	float3 posW = input.posW + input.velocity * t * (1 + 0.5f * gAccel * t);
	posW += rightVec * input.offset.x;
    posW += axis * input.offset.y;
    

    output.posH = mul(float4(posW, 1.0f), gVP);
	output.texc = input.texc;

	output.color = (1.0f - t/input.maxTime) * float4(input.color, 1.0f);

    return output;
}


float4 BillboardParticlePS(VSOutput input) : COLOR0
{
    return input.color * tex2D(Tex, input.texc);
}


float4 BillboardParticleNoColorPS(VSOutput input) : COLOR0
{
    return tex2D(Tex, input.texc);
}
////////



technique DynamicBillboardParticleAdditiveBlending
{
    pass P0
    {
        AlphaBlendEnable = true;
        SrcBlend = One;
        DestBlend = One;
		ZWriteEnable = false;

        VertexShader = compile vs_2_0 DynamicBillboardParticleVS();
        PixelShader = compile ps_2_0 BillboardParticlePS();
    }
}

technique DynamicBillboardParticleReplaceBlending
{
    pass P0
    {
        AlphaBlendEnable = true;
        SrcBlend = SrcAlpha;
        DestBlend = InvSrcAlpha;
		ZWriteEnable = false;

        VertexShader = compile vs_2_0 DynamicBillboardParticleVS();
        PixelShader = compile ps_2_0 BillboardParticlePS();
    }
}

technique AxisAlignedBillboardParticleAdditiveBlending
{
    pass P0
    {
        AlphaBlendEnable = true;
        SrcBlend = One;
        DestBlend = One;
		ZWriteEnable = false;

        VertexShader = compile vs_2_0 AxisAlignedBillboardParticleVS();
        PixelShader = compile ps_2_0 BillboardParticlePS();
    }
}

technique DynamicAxisAlignedBillboardParticleReplaceBlending
{
    pass P0
    {
        AlphaBlendEnable = true;
        SrcBlend = SrcAlpha;
        DestBlend = InvSrcAlpha;
		ZWriteEnable = false;

        VertexShader = compile vs_2_0 DynamicAxisAlignedBillboardParticleVS();
        PixelShader = compile ps_2_0 BillboardParticlePS();
    }
}

technique DynamicAxisAlignedBillboardParticleAdditiveBlending
{
    pass P0
    {
        AlphaBlendEnable = true;
        SrcBlend = One;
        DestBlend = One;
		ZWriteEnable = false;

        VertexShader = compile vs_2_0 DynamicAxisAlignedBillboardParticleVS();
        PixelShader = compile ps_2_0 BillboardParticlePS();
    }
}

technique AxisAlignedBillboardParticleAdditiveNoColor
{
    pass P0
    {
        AlphaBlendEnable = true;
        SrcBlend = One;
        DestBlend = One;
		ZWriteEnable = false;

        VertexShader = compile vs_2_0 AxisAlignedBillboardParticleVS();
        PixelShader = compile ps_2_0 BillboardParticleNoColorPS();
    }
}